import os  # 内置模块，提供许多操作的交互功能
import threading  # 内置模块，多线程支持，实现并发执行
from datetime import datetime  # 提供日期和时间的功能
from tkinter import filedialog  # 导入filedialog模块，实现对话框功能
import requests  # 常用的HTTP请求库，用于发送HTTP请求和处理响应
from Data import Data  # 自定义模块，数据处理和爬虫
from Spider import Spider  # 自定义模块，数据处理和爬虫
import tkinter as tk  # 导入GUI库，提供图形界面，创建窗口、标签、按钮、文本框
from tkinter import ttk  # 更好的外观与功能
from tkcalendar import (
    DateEntry,
)  # 提供一个可视化的日期选择器 # 常用的绘图库，提供一系列函数和库，提供图标与可视化效果

# 用于将Matplotlib图形嵌入到Tkinter应用程序的窗口中
from ttkthemes import (
    ThemedTk,
)  # 提供了一些自定义的主题和样式，创建Tkinter不同外观的应用程序窗口
import pandas as pd  # Pandas是一个强大的数据处理和分析工具，使数据处理变得更加简单和方便
import plotly.graph_objects as go  # 库，用于创建交互式绘图与可视化，散点图，线图等
from components import CustomDialog  # 自定义模块，对话框组件


# class Downloader(tk.Tk):
class Downloader(ThemedTk):
    def __init__(self, data):
        super().__init__()

        self.data = data  # 数据对象
        self.title("IERS数据下载助手")  # 窗口标题
        self.geometry("1000x450")  # 窗口大小

        # 使用 ttk 主题
        # style = ttk.Style()
        # style.theme_use('clam')  # 使用 'clam' 主题
        # self.set_theme('radiance')  # 使用 'radiance' 主题
        self.set_theme("breeze")  # 使用 'breeze' 主题

        # print(ThemedTk().get_themes())

        # 创建一个 frame 用于放置日期选择器和数据类型选择菜单
        frame1 = tk.Frame(self)
        frame1.pack(fill="x")
        tk.Label(frame1, text="选择爬取日期范围").grid(
            row=0, column=0, padx=5, pady=5, sticky="w"
        )
        self.start_date_entry = DateEntry(frame1, width=12)  # 开始日期选择器
        self.start_date_entry.grid(row=0, column=1, padx=5, pady=5, sticky="w")
        self.end_date_entry = DateEntry(frame1, width=12)  # 结束日期选择器
        self.end_date_entry.grid(row=0, column=2, padx=5, pady=5, sticky="w")
        tk.Label(frame1, text="选择数据类型").grid(row=0, column=3, padx=5, pady=5)
        self.file_types = [
            "选择",
            "BULLETIN A",
            "BULLETIN B",
            "BULLETIN C",
        ]  # 数据类型选项
        self.file_var = tk.StringVar()
        self.file_var.set(self.file_types[0])  # 默认选择第一个数据类型
        self.file_var.trace("w", self.update_tasks)  # 当数据类型变化时，更新任务列表
        self.file_menu = ttk.OptionMenu(
            frame1, self.file_var, *self.file_types
        )  # 数据类型选择菜单
        self.file_menu.config(width=15)
        self.file_menu.grid(row=0, column=4, padx=5, pady=5)

        # 选择自动更新天数菜单
        ttk.Label(frame1, text="  自动更新天数:").grid(row=0, column=5, padx=5, pady=5)
        self.update_days_choices = ["1天", "4天", "7天", "15天"]
        self.update_days_var = tk.StringVar()
        self.update_days_var.set("4天")
        self.update_days_var.trace("w", self.update_tasks)
        self.update_days_menu = ttk.OptionMenu(
            frame1, self.update_days_var, *self.update_days_choices
        )
        self.update_days_menu.config(width=10)
        self.update_days_menu.grid(row=0, column=6, padx=5, pady=5)

        # 创建一个 frame 用于放置文件路径输入框和按钮
        frame2 = tk.Frame(self)
        frame2.pack(fill="x")
        tk.Label(frame2, text="文件保存路径").grid(row=0, column=0, padx=5, pady=5)
        self.path_var = tk.StringVar()  # 文件保存路径
        self.path_entry = ttk.Entry(frame2, textvariable=self.path_var)  # 路径输入框
        self.path_entry.grid(row=0, column=1, padx=5, pady=5)
        self.browse_button = ttk.Button(
            frame2, text="浏览", command=self.browse, width=10
        )  # 浏览按钮
        self.browse_button.grid(row=0, column=2, padx=5, pady=5)
        self.download_button = ttk.Button(
            frame2, text="开始下载", command=self.download, width=10
        )  # 下载按钮
        self.download_button.grid(row=0, column=3, padx=5, pady=5)
        self.analysis_button = ttk.Button(
            frame2, text="可视化分析", command=self.analysis, width=10
        )
        self.analysis_button.grid(row=0, column=4, padx=5, pady=5)

        # 创建一个 frame 用于放置下载进度条
        frame3 = tk.Frame(self)
        frame3.pack(fill="x")
        tk.Label(frame3, text="下载进度").grid(row=0, column=0, padx=5, pady=5)
        self.progress = ttk.Progressbar(frame3, length=750)  # 下载进度条
        self.progress.grid(row=0, column=1, columnspan=3, padx=5, pady=5)

        # 创建一个 frame 用于放置任务列表
        frame4 = tk.Frame(self)
        frame4.pack(fill="both", expand=True)
        tk.Label(frame4, text="任务列表").grid(row=0, column=0, padx=400, pady=5)
        self.task_list = ttk.Treeview(
            frame4,
            columns=(
                "数据类型",
                "Title",
                "Date",
                "Text File",
                "HTML File",
                "CSV File",
                "下载状态",
            ),
            show="headings",
        )  # 任务列表
        self.task_list.column("数据类型", width=120)
        self.task_list.column("Title", width=120)
        self.task_list.column("Date", width=120)
        self.task_list.column("Text File", width=120)
        self.task_list.column("HTML File", width=120)
        self.task_list.column("下载状态", width=120)
        self.task_list.heading("数据类型", text="数据类型")
        self.task_list.heading("Title", text="Title")
        self.task_list.heading("Date", text="Date")
        self.task_list.heading("Text File", text="Text File")
        self.task_list.heading("HTML File", text="HTML File")
        self.task_list.heading("CSV File", text="CSV File")
        self.task_list.heading("下载状态", text="下载状态")
        self.task_list.grid(row=1, column=0, columnspan=4, padx=5, pady=5)

    def browse(self):
        self.path_var.set(filedialog.askdirectory())  # 选择文件保存路径

    def warning(self):
        CustomDialog(app, title="", message="无所需数据")

    def download(self):
        if len(self.data.tasks) == 0:
            self.warning()
        def download_thread():
            self.data.save_path = self.path_var.get()  # 获取文件保存路径
            for i, task in enumerate(self.data.tasks):  # 遍历任务列表
                (
                    file_type,
                    title,
                    date,
                    textfile_url,
                    htmlfile_url,
                    csvfile_url,
                    status,
                ) = task
                if status == "准备下载":
                    # 创建文件夹
                    folder_path = os.path.join(
                        self.data.save_path, file_type + "-" + date
                    )
                    os.makedirs(folder_path, exist_ok=True)

                    # 下载并保存文本文件
                    response = requests.get(textfile_url)
                    with open(os.path.join(folder_path, "file.txt"), "wb") as f:
                        f.write(response.content)

                    # 下载并保存HTML文件
                    response = requests.get(htmlfile_url)
                    with open(os.path.join(folder_path, "file.html"), "wb") as f:
                        f.write(response.content)

                    # 下载并保存CSV文件
                    response = requests.get(csvfile_url)
                    with open(os.path.join(folder_path, "file.csv"), "wb") as f:
                        f.write(response.content)

                    # 更新任务状态
                    task = (
                        file_type,
                        title,
                        date,
                        textfile_url,
                        htmlfile_url,
                        csvfile_url,
                        "下载完成",
                    )
                    item_id = self.task_list.insert("", "end", values=task)
                    self.task_list.item(item_id, values=task)

                    # 更新下载进度条
                    self.progress.step(100.0 / len(self.data.tasks))

        threading.Thread(target=download_thread).start()

    def update_tasks(self, *args):
        def update_tasks_thread():
            self.data.start_date = datetime.strptime(
                self.start_date_entry.get(), "%m/%d/%y"
            ).date()  # 获取选择的开始日期
            self.data.end_date = datetime.strptime(
                self.end_date_entry.get(), "%m/%d/%y"
            ).date()  # 获取选择的结束日期
            self.data.file_type = self.file_var.get()  # 获取选择的数据类型
            self.data.tasks.clear()
            Spider.fetch_data(self.data)  # 爬取数据
            self.task_list.delete(*self.task_list.get_children())  # 清空任务列表
            for task in self.data.tasks:  # 更新任务列表
                self.task_list.insert("", "end", values=task)

        file_type = self.file_var.get()
        if file_type == "选择":
            return
        threading.Thread(target=update_tasks_thread).start()

    def analysis(self):
        # 获取信息后下载
        self.data.start_date = datetime.strptime(
            self.start_date_entry.get(), "%m/%d/%y"
        ).date()  # 获取选择的开始日期
        self.data.end_date = datetime.strptime(
            self.end_date_entry.get(), "%m/%d/%y"
        ).date()  # 获取选择的结束日期
        self.data.file_type = self.file_var.get()  # 获取选择的数据类型
        self.data.tasks.clear()
        Spider.fetch_data(self.data)  # 爬取数据

        self.data.save_path = ""
        csv_files = []
        for i, task in enumerate(self.data.tasks):  # 遍历任务列表
            (
                file_type,
                title,
                date,
                textfile_url,
                htmlfile_url,
                csvfile_url,
                status,
            ) = task
            if status == "准备下载":
                # 创建文件夹
                folder_path = os.path.join(self.data.save_path, file_type + "-" + date)
                os.makedirs(folder_path, exist_ok=True)

                # 下载并保存文本文件
                response = requests.get(textfile_url)
                with open(os.path.join(folder_path, "file.txt"), "wb") as f:
                    f.write(response.content)

                # 下载并保存HTML文件
                response = requests.get(htmlfile_url)
                with open(os.path.join(folder_path, "file.html"), "wb") as f:
                    f.write(response.content)

                # 下载并保存CSV文件
                response = requests.get(csvfile_url)
                with open(os.path.join(folder_path, "file.csv"), "wb") as f:
                    f.write(response.content)
                    csv_files.append(os.path.join(folder_path, "file.csv"))

        # 读取 CSV 文件
        df = pd.concat([pd.read_csv(f, delimiter=";") for f in csv_files])
        # df = pd.read_csv('BULLETIN A-2024-02-08/file.csv', delimiter=';')

        # 将年、月、日组合成一个日期
        df["Date"] = pd.to_datetime(df[["Year", "Month", "Day"]])

        # 创建一个三维图表
        fig = go.Figure(
            data=[
                go.Scatter3d(
                    x=df["x_pole"],
                    y=df["y_pole"],
                    z=df["Date"],
                    mode="lines",
                    line=dict(color="blue", width=2),
                )
            ]
        )

        # 设置图表的布局
        fig.update_layout(
            title="地球极移路径图",
            scene=dict(
                xaxis_title="x_pole",
                yaxis_title="y_pole",
                zaxis_title="日期",
                bgcolor="black",
            ),
            font=dict(family="Courier New, monospace", size=14, color="white"),
        )

        # 显示图表
        fig.show()


if __name__ == "__main__":
    data = Data()  # 创建数据对象
    app = Downloader(data)  # 创建下载器对象
    app.mainloop()  # 启动主循环
